package com.xz.stu.server.service.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONNull;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.stu.server.entity.Department;
import com.xz.stu.server.entity.StuClass;
import com.xz.stu.server.entity.Student;
import com.xz.stu.server.service.ClassService;
import com.xz.stu.server.service.DepartmentService;
import com.xz.stu.server.service.StudentService;
import com.xz.stu.server.mapper.StudentMapper;
import com.xz.stu.server.vo.student.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;


/**
* @author 熊磊
* @description 针对表【school_student】的数据库操作Service实现
* @createDate 2025-03-01 15:18:51
*/
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService{
    @Resource
    private ClassService classService;
    @Resource
    private DepartmentService departmentService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private AdminUserService adminUserService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private RoleMapper roleMapper;


    @Override
    public Long createStudent(StudentCreateReqVO createReqVO) {
        Student student = BeanUtils.toBean(createReqVO, Student.class);
        //判断学号是否已存在
        if (this.getOne(new LambdaQueryWrapper<Student>().eq(Student::getStudentId, createReqVO.getStudentId())) != null) {
            throw new ServiceException(new ErrorCode(100000000,"学号已存在"));
        }
        //判断班级是否存在
        if (classService.getById(createReqVO.getClassId()) == null) {
            throw new ServiceException(new ErrorCode(100000000,"班级不存在"));
        }
        AdminUserDO adminUserDO = new AdminUserDO();
        adminUserDO.setUsername(student.getStudentId());
        adminUserDO.setPassword(passwordEncoder.encode("123456"));
        adminUserDO.setNickname(student.getName());
        adminUserDO.setMobile(student.getPhone());
        adminUserDO.setSex(student.getGender());
        adminUserDO.setStatus(0);
        adminUserService.save(adminUserDO);
        student.setUserId(adminUserDO.getId());
        //添加角色信息
        RoleDO roleDO = roleMapper.selectOne(RoleDO::getName, "学生");
        UserRoleDO userRoleDO = new UserRoleDO();
        userRoleDO.setUserId(adminUserDO.getId());
        userRoleDO.setRoleId(roleDO.getId());
        userRoleMapper.insert(userRoleDO);
        this.save(student);
        return student.getId();
    }

    @Override
    public void updateStudent(StudentUpdateReqVO updateReqVO) {
        Student student = BeanUtils.toBean(updateReqVO, Student.class);
        //判断学号是否已存在
        if (this.getOne(new LambdaQueryWrapper<Student>().eq(Student::getStudentId, updateReqVO.getStudentId())) != null) {
            throw new ServiceException(new ErrorCode(100000000,"学号已存在"));
        }
        //判断班级是否存在
        if (classService.getById(updateReqVO.getClassId()) == null) {
            throw new ServiceException(new ErrorCode(100000000,"班级不存在"));
        }
        this.updateById(student);
    }

    @Override
    @Transactional
    public void deleteStudent(List<Long> id) {
        List<Long> userIds = this.listByIds(id).stream().map(Student::getUserId).collect(Collectors.toList());
        //删除用户角色信息
        adminUserService.removeByIds(userIds);
        userRoleMapper.delete(new LambdaQueryWrapper<UserRoleDO>().in(UserRoleDO::getUserId, userIds));
        this.removeByIds(id);

    }

    @Override
    public StudentRespVO getStudent(Long id) {
        Map<Long, String> deptmap = departmentService.list().stream().collect(Collectors.toMap(Department::getId, Department::getDeptName));
        Map<Long, StuClass> stringMap = classService.list().stream().collect(Collectors.toMap(StuClass::getId, Function.identity()));
        Student student = this.getById(id);
        StudentRespVO studentRespVO = BeanUtils.toBean(student, StudentRespVO.class);
        studentRespVO.setClassName(stringMap.get(student.getClassId()).getClassName());
        studentRespVO.setDeptId(stringMap.get(student.getClassId()).getDeptId());
        studentRespVO.setDeptName(deptmap.get(studentRespVO.getDeptId()));
        return studentRespVO;

    }

    @Override
    public List<StudentRespVO> getStudentList(StudentListReqVO listReqVO) {
        List<Student> list = this.list();
        return  BeanUtils.toBean(list, StudentRespVO.class);

    }

    @Override
    public PageResult<StudentRespVO> getStudentListPage(StudentListPageReqVO listReqVO) {
        Map<Long, String> deptmap = departmentService.list().stream().collect(Collectors.toMap(Department::getId, Department::getDeptName));
        Map<Long, StuClass> stringMap = classService.list().stream().collect(Collectors.toMap(StuClass::getId, Function.identity()));
        LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Objects.nonNull(listReqVO.getStudentId()), Student::getStudentId, listReqVO.getStudentId())
                .like(Objects.nonNull(listReqVO.getName()), Student::getName, listReqVO.getName())
                .eq(Objects.nonNull(listReqVO.getGender()), Student::getGender, listReqVO.getGender())
                .eq(Objects.nonNull(listReqVO.getClassId()), Student::getClassId, listReqVO.getClassId());
        Page<Student> page = this.page(new Page<>(listReqVO.getPageNo(), listReqVO.getPageSize()), lambdaQueryWrapper);
        if (page != null) {
            List<StudentRespVO> studentRespVOList = BeanUtils.toBean(page.getRecords(), StudentRespVO.class);
            studentRespVOList.forEach(studentRespVO -> {
                studentRespVO.setClassName(stringMap.get(studentRespVO.getClassId()).getClassName());
                studentRespVO.setDeptName(deptmap.get(stringMap.get(studentRespVO.getClassId()).getDeptId()));
            });
            return new PageResult<>(studentRespVOList, page.getTotal());
        }
        return null;
    }

    @Override
    @Transactional
    public CommonResult<Map<String,String>> importStudents(List<StudentTemplateVO> students) {
        HashMap<String,String> map = new HashMap<>();
        if (students == null || students.isEmpty()) {
            map.put("code", "301");
            map.put("msg", "文件为空，请选择有效的 Excel 文件。");
            return success(map);
        }
        List<Department> departmentList = departmentService.list();
        List<StuClass> stuClassList = classService.list();

        List<StudentTemplateAbnormalVO> list = new ArrayList<>();
        this.extracted(students, departmentList, stuClassList, list);
        if (!list.isEmpty()){
            Long id = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUser()).getId();
            //构架key
            String key = "student:import:abnormal:" + id;
            //将异常存入redis
            redisTemplate.opsForValue().set(key, JsonUtils.toJsonPrettyString(list), 1, TimeUnit.MINUTES);
            map.put("code", "101");
            map.put("msg", "导入失败，为您下载错误信息。");
            return success(map);
        }
        List<Student> studentList = students.stream().map(student -> {
            Student stu = BeanUtils.toBean(student, Student.class);
            stu.setGender(student.getGenderC().equals("男") ? 0 : 1);
            Optional<StuClass> first = stuClassList.stream()
                    .filter(stuClass -> stuClass.getClassName().equals(student.getClassName())).
                    findFirst();
            first.ifPresent(stuClass -> stu.setClassId(stuClass.getId()));
            AdminUserDO adminUserDO = new AdminUserDO();
            adminUserDO.setUsername(student.getStudentId());
            adminUserDO.setPassword(passwordEncoder.encode("123456"));
            adminUserDO.setNickname(student.getName());
            adminUserDO.setMobile(student.getPhone());
            adminUserDO.setSex(stu.getGender());
            adminUserDO.setStatus(0);
            adminUserService.save(adminUserDO);
            stu.setUserId(adminUserDO.getId());
            //添加角色信息
            RoleDO roleDO = roleMapper.selectOne(RoleDO::getName, "学生");
            UserRoleDO userRoleDO = new UserRoleDO();
            userRoleDO.setUserId(adminUserDO.getId());
            userRoleDO.setRoleId(roleDO.getId());
            userRoleMapper.insert(userRoleDO);
            return stu;
        }).collect(Collectors.toList());
        this.saveBatch(studentList);

        map.put("code", "200");
        map.put("msg","导入成功，共导入 " + students.size() + " 条学生信息。");
        return success(map);
    }

    private void extracted(List<StudentTemplateVO> students, List<Department> departmentList, List<StuClass> stuClassList, List<StudentTemplateAbnormalVO> list) {
        List<String> studentIds = this.list().stream().map(Student::getStudentId).collect(Collectors.toList());

        List<String> deptList = departmentList.stream().map(Department::getDeptName).collect(Collectors.toList());
        Map< Long,String> deptMap = departmentList.stream().collect(Collectors.toMap(Department::getId,Department::getDeptName));

        List<String> classNameList = stuClassList.stream().map(StuClass::getClassName).collect(Collectors.toList());
        Map<String, List<String>> listMap = new HashMap<>();
        for (StuClass stuClass : stuClassList) {
            String deptName = deptMap.get(stuClass.getDeptId());
            if (listMap.containsKey(deptName)){
                listMap.get(deptName).add(stuClass.getClassName());
            }else {
                List<String> strings = new ArrayList<>();
                strings.add(stuClass.getClassName());
                listMap.put(deptName,strings);
            }
        }

        for (StudentTemplateVO student : students) {
            //判断学号是否重复
            if (studentIds.contains(student.getStudentId())){
                StudentTemplateAbnormalVO studentTemplateAbnormalVO = BeanUtils.toBean(student, StudentTemplateAbnormalVO.class);
                studentTemplateAbnormalVO.setErrorMsg("学号重复");
                list.add(studentTemplateAbnormalVO);
            }
            //判断班级是否存在
            if (!classNameList.contains(student.getClassName())){
                StudentTemplateAbnormalVO studentTemplateAbnormalVO = BeanUtils.toBean(student, StudentTemplateAbnormalVO.class);
                studentTemplateAbnormalVO.setErrorMsg("班级不存在");
                list.add(studentTemplateAbnormalVO);
            }else {
                //判断院系是否存在
                if (!deptList.contains(student.getDeptName())){
                    StudentTemplateAbnormalVO studentTemplateAbnormalVO = BeanUtils.toBean(student, StudentTemplateAbnormalVO.class);
                    studentTemplateAbnormalVO.setErrorMsg("院系不存在");
                    list.add(studentTemplateAbnormalVO);
                    break;
                }
                //判断的院系下的班级是否存在
                if (!listMap.get(student.getDeptName()).contains(student.getClassName())){
                    StudentTemplateAbnormalVO studentTemplateAbnormalVO = BeanUtils.toBean(student, StudentTemplateAbnormalVO.class);
                    studentTemplateAbnormalVO.setErrorMsg("班级不在院系下");
                    list.add(studentTemplateAbnormalVO);
                }
            }
        }
    }

}




